package com.elitel.frame.business.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.elitel.common.exception.BaseException;
//import com.elitel.common.redis.service.RedisCacheService;
import com.elitel.frame.base.component.RedisCacheComponent;
import com.elitel.frame.base.component.RedisCatchCensus;
import com.elitel.frame.base.service.CfgExtsqlService;
import com.elitel.frame.base.service.CfgMoreJoinService;
import com.elitel.frame.base.service.DBServerService;
import com.elitel.frame.business.service.MultipleTableServerService;
import com.elitel.frame.business.service.SingleTableServerService;
import com.elitel.frame.business.service.TableFieldCommService;
import com.elitel.frame.main.entity.*;
import com.elitel.frame.main.entity.ext.QueryFiled;
import com.elitel.frame.main.entity.ext.ReturnData;
import com.elitel.frame.main.entity.vo.JsonDataResult;
import com.elitel.frame.main.entity.vo.PageResponseVo;
import com.google.gson.JsonObject;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <pre>@ProjectName：frame-business-web
 * @ClassName：MoreJoinTableServerController
 * @Description: TODO(多表跨库查询)
 * @version </pre>
 */
@Controller
@RequestMapping("/business/moreJoinTable")
@Api(value = "/business/moreJoinTable", tags = "脚本服务接口")
public class MoreJoinTableServerController {
    private static final Logger logger = LoggerFactory.getLogger(MoreJoinTableServerController.class);

    @Autowired
    private CfgMoreJoinService cfgMoreJoinService;
    @Autowired
    private CfgExtsqlService cfgExtsqlService;
    @Resource
    private DBServerService dbServerServiceImpl;
    @Autowired
    private MultipleTableServerService multipleTableServerService;
    @Autowired
    private SingleTableServerService singleTableServerService;
    @Autowired
    private TableFieldCommService tableFieldCommService;

//    @Resource
//    private RedisCacheService redisCacheService;

    @Resource
    private RedisCatchCensus redisCatchCensus;

    @Autowired
    private RedisCacheComponent redisCacheComponent;

    private int rdi = 0;

    /**
     * TODO: 根据 serviceId 判断是否使用分页
     *
     * @param serviceId
     * @return
     */
    @GetMapping("/isPage")
    @ResponseBody
    @ApiOperation(notes = "/isPage", value = "根据 serviceId 判断是否使用分页")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "serviceId", value = "服务编码", required = true, dataType = "String", paramType = "query")
    })
    public Object isPage(@RequestParam(value = "serviceId") String serviceId) {
        JsonDataResult jsonDataResult = new JsonDataResult();
        try {
            CfgMoreJoin cfgMoreJoin = cfgMoreJoinService.getCfgMoreJoinByGuid(serviceId);
            jsonDataResult.setData(cfgMoreJoin);
            jsonDataResult.setMessage("查询成功");
            jsonDataResult.setResult(0);
        } catch (BaseException e) {
            e.printStackTrace();
            jsonDataResult.setMessage(e.getExceptionVO().getDesc());
            jsonDataResult.setResult(1);
        }
        return jsonDataResult;
    }

    /**
     * TODO: 根据服务编码执行多表跨库查询服务
     *
     * @param serviceId
     * @return
     * @throws Exception
     */
    @ApiOperation(notes = "/moreJoinTableServer", value = "根据服务编码查询多表跨库查询服务")
    @RequestMapping(value = "/moreJoinTableServer", method = RequestMethod.GET)
    @ResponseBody
    @ApiImplicitParams({
            @ApiImplicitParam(name = "serviceId", value = "服务编码", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "conQuery", value = "查询条件集合", required = false, dataType = "String", paramType = "query")
    })
    public Object moreJoinTableServer(@RequestParam(value = "serviceId") String serviceId, String conQuery) throws Exception {

        JsonDataResult jsonDataResult = new JsonDataResult();
        try {

            CfgMoreJoin cfgMoreJoin = cfgMoreJoinService.getCfgMoreJoinByGuid(serviceId);
            PageResponseVo pageResponseVo = getMoreJoinData(cfgMoreJoin, conQuery);

            jsonDataResult.setData(pageResponseVo);
            jsonDataResult.setMessage("查询成功");
            jsonDataResult.setResult(0);
        } catch (BaseException e) {
            e.printStackTrace();
            jsonDataResult.setMessage(e.getExceptionVO().getDesc());
            jsonDataResult.setResult(1);
        }
        return jsonDataResult;
    }


    /**
     * TODO: 根据服务编码执行多表跨库查询服务 分页
     *
     * @param serviceId
     * @return
     * @throws Exception
     */
    @ApiOperation(notes = "/moreJoinTableServerByPage", value = "根据服务编码分页查询多表跨库查询服务")
    @RequestMapping(value = "/moreJoinTableServerByPage", method = RequestMethod.GET)
    @ApiImplicitParams({
            @ApiImplicitParam(name = "serviceId", value = "服务编码", required = true, dataType = "String", paramType = "query"),
            @ApiImplicitParam(name = "pageNO", value = "当前页码", required = false, dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "pageSize", value = "每页条数", required = false, dataType = "Integer", paramType = "query"),
            @ApiImplicitParam(name = "conQuery", value = "查询条件集合", required = false, dataType = "String", paramType = "query"),
    })
    @ResponseBody
    public Object moreJoinTableServerByPage(@RequestParam(value = "serviceId") String serviceId, Integer pageNO, Integer pageSize, String conQuery) throws Exception {

        JsonDataResult jsonDataResult = new JsonDataResult();
        try {
            CfgMoreJoin cfgMoreJoin = cfgMoreJoinService.getCfgMoreJoinByGuid(serviceId);
            PageResponseVo pageResponseVo = getMoreJoinData(cfgMoreJoin, conQuery);

            if (pageResponseVo.getRows() != null) {
                // 设置默认值
                pageNO = (pageNO == null || pageNO == 0) ? 1 : pageNO;
                pageSize = (pageSize == null || pageSize == 0) ? 10 : pageSize;

                // 使用内存分页
                int fromIndex = 0, toIndex = 0, recount = pageResponseVo.getRows().size();
                fromIndex = pageSize * (pageNO - 1);
                toIndex = fromIndex + pageSize >= recount ? recount : fromIndex + pageSize;

                pageResponseVo.setRows(pageResponseVo.getRows().subList(fromIndex, toIndex));
                pageResponseVo.setTotal(recount);
            } else {
                pageResponseVo.setRows(null);
                pageResponseVo.setTotal(0);
            }

            jsonDataResult.setData(pageResponseVo);
            jsonDataResult.setMessage("查询成功");
            jsonDataResult.setResult(0);
        } catch (BaseException e) {
            e.printStackTrace();
            jsonDataResult.setMessage(e.getExceptionVO().getDesc());
            jsonDataResult.setResult(1);
        }

        return jsonDataResult;
    }

    /**
     * TODO: 根据服务编码获取字段列
     *
     * @param serviceId
     * @return
     */
    @ApiOperation(notes = "/selectAllColumn", value = "根据服务编码获取字段列")
    @RequestMapping(value = "/selectAllColumn", method = RequestMethod.GET)
    @ResponseBody
    @ApiImplicitParams({
            @ApiImplicitParam(name = "serviceId", value = "服务编码", required = true, dataType = "String", paramType = "query")
    })
    public Object selectAllColumn(@RequestParam(value = "serviceId") String serviceId) {

        JsonDataResult jsonDataResult = new JsonDataResult();

        try {

            CfgMoreJoin cfgMoreJoin = cfgMoreJoinService.getCfgMoreJoinByGuid(serviceId);
            JSONArray jsonArray = JSONArray.parseArray(cfgMoreJoin.getRelatedServices());

            // 获取 service1 获取列表列名
            JSONObject service1 = (JSONObject) jsonArray.get(0);
            List<Map<String, String>> fieldService1 = getShowField(service1);

            // 获取 service2 获取列表列名
            JSONObject service2 = (JSONObject) jsonArray.get(1);
            List<Map<String, String>> fieldService2 = getShowField(service2);

            fieldService1.addAll(fieldService2);

            jsonDataResult.setData(fieldService1);
            jsonDataResult.setMessage("查询成功");
            jsonDataResult.setResult(0);
        } catch (BaseException e) {
            e.printStackTrace();
            jsonDataResult.setMessage(e.getExceptionVO().getDesc());
            jsonDataResult.setResult(1);
        }

        return jsonDataResult;
    }


    /**
     * TODO: 根据服务编码获取查询字段
     *
     * @param serviceId
     * @return
     */
    @ApiOperation(notes = "/selectQueryFiled", value = "根据服务编码获取查询字段")
    @RequestMapping(value = "/selectQueryFiled", method = RequestMethod.GET)
    @ResponseBody
    @ApiImplicitParams({
            @ApiImplicitParam(name = "serviceId", value = "服务编码", required = true, dataType = "String", paramType = "query")
    })
    public Object selectQueryFiled(@RequestParam(value = "serviceId") String serviceId) {
        JsonDataResult jsonDataResult = new JsonDataResult();
        try {
            CfgMoreJoin cfgMoreJoin = cfgMoreJoinService.getCfgMoreJoinByGuid(serviceId);
            JSONArray jsonArray = JSONArray.parseArray(cfgMoreJoin.getRelatedServices());

            // 获取 service1 获取查询条件
            JSONObject service1 = (JSONObject) jsonArray.get(0);
            List<Map<String, String>> querySearchService1 = getSearchField(service1);

            // 获取 service2 获取查询条件
            JSONObject service2 = (JSONObject) jsonArray.get(1);
            List<Map<String, String>> querySearchService2 = getSearchField(service2);

            // 合并两个查询条件结果
            querySearchService1.addAll(querySearchService2);

            jsonDataResult.setData(querySearchService1);
            jsonDataResult.setMessage("查询成功");
            jsonDataResult.setResult(0);

        } catch (BaseException e) {
            e.printStackTrace();
            jsonDataResult.setMessage(e.getExceptionVO().getDesc());
            jsonDataResult.setResult(1);
        }
        //getSearchField
        return jsonDataResult;
    }


    /**
     * TODO: 根据关联的 serviceId 获取数据
     *
     * @param service
     * @param conQuery
     * @return
     * @throws Exception
     */
    private PageResponseVo getPageResponseVoBy(JSONObject service, String conQuery) throws Exception {
        String serviceId = service.getString("value");
        String serviceType = service.getString("type");

        PageResponseVo result = new PageResponseVo();

        switch (serviceType) {
            case "executeSqlServer":
                CfgExtsql cfgExtsql = cfgExtsqlService.selectCfgSqlByPrimary(serviceId);
                CfgDb cfgDB = dbServerServiceImpl.getCfgDbOne(cfgExtsql.getDtDbKey());
                result = multipleTableServerService.multipleTableServerQuery(cfgDB, conQuery, cfgExtsql, "false");
                break;
            case "singleTableServer":
                CfgExtend cfgExtend = redisCacheComponent.cfgExtendRedisCache(serviceId);
                CfgDb prop = redisCacheComponent.cfgDBRedisCache(cfgExtend.getDbKey());
//                result = singleTableServerService.querySingleTBNOPage(prop, cfgExtend, conQuery, "false");
                break;
        }
        return result;
    }

    /**
     * TODO: 获取列表列名
     *
     * @param service
     * @return
     * @throws Exception
     */
    private List<Map<String, String>> getShowField(JSONObject service) {
        String serviceId = service.getString("value");
        String serviceType = service.getString("type");

        List<Map<String, String>> result = new ArrayList<>();
        switch (serviceType) {
            case "executeSqlServer":
                String key = "BASE_SQLCONFIG_" + serviceId;
//                if(redisCacheService.stringExists(key, rdi)){
//                    List<ReturnData> list = redisCatchCensus.getSqlConfigCache(serviceId);
//                    for(ReturnData b:list){
//                        Map map = new HashMap();
//                        map.put("filedname",b.getFieldname());
//                        map.put("fieldcaption",b.getFieldnamecn());
//                        result.add(map);
//                    }
//                }else {
//                    List<BaseSqlconfig> list = dbServerServiceImpl.selectServerColumn(serviceId);
//                    for(BaseSqlconfig b:list){
//                        Map map = new HashMap();
//                        map.put("filedname",b.getFiledname());
//                        map.put("fieldcaption",b.getFieldcaption());
//                        result.add(map);
//                    }
//                }
                List<ReturnData> list = redisCatchCensus.getSqlConfigCache(serviceId);
                for (ReturnData b : list) {
                    Map map = new HashMap();
                    map.put("filedname", b.getFieldname());
                    map.put("fieldcaption", b.getFieldnamecn());
                    result.add(map);
                }
                break;
            case "singleTableServer":
                CfgExtend cfgExtend = redisCacheComponent.cfgExtendRedisCache(serviceId);
                CfgDb cfgDb = redisCacheComponent.cfgDBRedisCache(cfgExtend.getDbKey());
                result = tableFieldCommService.getServiceShowField(cfgDb, serviceId, "1", "");
                break;
        }

        return result;
    }

    /**
     * TODO: 获取查询条件
     *
     * @param service
     * @return
     * @throws Exception
     */
    private List<Map<String, String>> getSearchField(JSONObject service) {
        String serviceId = service.getString("value");
        String serviceType = service.getString("type");

        List<Map<String, String>> result = new ArrayList<>();
        switch (serviceType) {
            case "executeSqlServer":
                List<QueryFiled> list2 = new ArrayList<>();
                list2 = dbServerServiceImpl.selectServerField(serviceId);
                for (QueryFiled queryFiled : list2) {
                    Map<String, String> dataMap = new HashMap<>();
                    dataMap.put("fieldname", queryFiled.getParametercode());
                    if (queryFiled.getParametervalue() == null || "".equals(queryFiled.getParametervalue())) {
                        dataMap.put("fieldnamecn", queryFiled.getParametercode());
                    } else {
                        dataMap.put("fieldnamecn", queryFiled.getParametervalue());
                    }
                    dataMap.put("fieldtype", "string");
                    dataMap.put("showtype", queryFiled.getShowtype());
                    dataMap.put("enumvalue", null);
                    result.add(dataMap);
                }
                break;
            case "singleTableServer":
                CfgExtend cfgExtend = redisCacheComponent.cfgExtendRedisCache(serviceId);
                CfgDb cfgDb = redisCacheComponent.cfgDBRedisCache(cfgExtend.getDbKey());
                result = tableFieldCommService.getTableQueryField(cfgDb, serviceId, 1, "");
                break;
        }
        return result;
    }


    /**
     * TODO: 获取多表跨库查询数据
     *
     * @param cfgMoreJoin
     * @param conQuery
     * @return
     * @throws Exception
     */
    private PageResponseVo getMoreJoinData(CfgMoreJoin cfgMoreJoin, String conQuery) throws Exception {

        PageResponseVo result = new PageResponseVo();

        JSONArray jsonArray = JSONArray.parseArray(cfgMoreJoin.getRelatedServices());
        String[] relatedKey = cfgMoreJoin.getRelatedKey().split(",");

        // 获取 service1 数据
        JSONObject service1 = (JSONObject) jsonArray.get(0);
        PageResponseVo<HashMap<String, Object>> pageResponse1 = getPageResponseVoBy(service1, conQuery);
        String serviceKey1 = relatedKey[0];

        // 获取 service2 数据
        JSONObject service2 = (JSONObject) jsonArray.get(1);
        PageResponseVo<HashMap<String, Object>> pageResponse2 = getPageResponseVoBy(service2, conQuery);
        String serviceKey2 = relatedKey[1];

        List<Map> servicesData = new ArrayList<>();

        // 如果不使用缓存，或缓存中没有数据，则读取数据
//        if (cfgMoreJoin.getSyscatch() != 1 || redisCacheService.getObject(cfgMoreJoin.getGuid(),0).equals("")){
        // 循环遍历服务查询结果，合并结果值
        if ((pageResponse1.getTotal() != null && pageResponse1.getTotal() > 0) && (pageResponse2.getTotal() != null && pageResponse2.getTotal() > 0)) {
            for (int i = 0; i < pageResponse1.getTotal(); i++) {
                Map objectService1 = pageResponse1.getRows().get(i);
                String relateKey1 = objectService1.get(serviceKey1).toString();

                for (int j = 0; j < pageResponse2.getTotal(); j++) {
                    Map objectService2 = pageResponse2.getRows().get(j);
                    String relateKey2 = objectService2.get(serviceKey2).toString();
                    if (relateKey1.equals(relateKey2)) {
                        objectService1.putAll(objectService2);
                        servicesData.add(objectService1);
                    }
                }
            }
            result.setRows(servicesData);
            result.setTotal(servicesData.size());

            // 保存数据到缓存
//                String data = JSON.toJSONString(servicesData);
//                redisCacheService.saveObject(cfgMoreJoin.getGuid(), data, rdi);
        }
//        }else{
//            // 获取缓存数据
//            String data = redisCacheService.getObject(cfgMoreJoin.getGuid(),rdi);
//            List<Map> dataList = JSON.parseArray(data, Map.class);
//            result.setRows(dataList);
//            result.setTotal(dataList.size());
//        }

        return result;
    }
}
